package com.edison.demo.service.impl;

import com.edison.demo.entity.ConsumerBaseInfo;
import com.edison.demo.entity.CustomerPersonalBasicInfo;
import com.edison.demo.service.DataBatchService;
import com.edison.demo.service.DataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
 * @author edison
 */
@Slf4j
@Service
public class DataBatchServiceImpl implements DataBatchService {




    private final DataService<ConsumerBaseInfo> consumerBaseInfoDataService;
    private final DataService<CustomerPersonalBasicInfo> customerPersonalBasicInfoDataService;

    @Autowired
    public DataBatchServiceImpl(DataService<ConsumerBaseInfo> consumerBaseInfoDataService, DataService<CustomerPersonalBasicInfo> customerPersonalBasicInfoDataService) {
        this.consumerBaseInfoDataService = consumerBaseInfoDataService;
        this.customerPersonalBasicInfoDataService = customerPersonalBasicInfoDataService;
    }

    @Override
    @Async
    public CompletableFuture<Integer> generateConsumerBaseInfo(int batchSize) throws ExecutionException, InterruptedException {
        return generateData(batchSize,consumerBaseInfoDataService);
    }

    @Override
    @Async
    public CompletableFuture<Integer> generateCustomerPersonalBasicInfo(int batchSize) throws ExecutionException, InterruptedException {
        return generateData(batchSize,customerPersonalBasicInfoDataService);
    }


    public <T> CompletableFuture<Integer> generateData(int batchSize, DataService<T> dataService) throws ExecutionException, InterruptedException {
        // Init data
        log.info("Creating mock data, batch size: {}", batchSize);
        CompletableFuture<List<T>> dataFuture = dataService.initData(batchSize);
        List<T> dataList = dataFuture.get();
        log.info("Mock data creation completed, {} records created", dataList.size());

        // Batch insert
        List<CompletableFuture<Integer>> updateFutures = new ArrayList<>();
        int totalInserted = 0;
        int batchInsertSize = 3000;
        log.info("Inserting data into DB in batches of {}", batchInsertSize);

        for (int i = 0; i < dataList.size(); i += batchInsertSize) {
            List<T> batch = dataList.subList(i, Math.min(i + batchInsertSize, dataList.size()));
            updateFutures.add(dataService.batchInsert(batch));
        }

        for (CompletableFuture<Integer> future : updateFutures) {
            totalInserted += future.get();
        }

        log.info("{} records inserted into DB", totalInserted);
        return CompletableFuture.completedFuture(totalInserted);
    }
}
